package demo.aio;


import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

/**
 * @author <a href="eric_zheng@lanzuo.com.cn">eric</a>
 * @version 1.0.0
 * @description 处理异步io的结果的处理器
 */
public abstract class ChannelAdapter implements CompletionHandler<Integer, Object> {

    private AsynchronousSocketChannel socketChannel;
    private Charset charset;

    public ChannelAdapter(AsynchronousSocketChannel socketChannel, Charset charset) {
        this.socketChannel = socketChannel;
        this.charset = charset;
        if (socketChannel.isOpen()) {
            channelActive(new ChannelHandler(socketChannel, charset));
        }

    }

    @Override
    public void completed(Integer result, Object attachment) {
        try {
            // 分配缓存
            final ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            final long timeout = 60 * 60L;
            socketChannel.read(byteBuffer, timeout, TimeUnit.SECONDS, null,
                    new CompletionHandler<Integer, Object>() {
                        @Override
                        public void completed(Integer result, Object attachment) {
                            if (result == -1) {
                                try {
                                    channelInactive(new ChannelHandler(socketChannel, charset));
                                    socketChannel.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }

                                return;
                            }
                            byteBuffer.flip();
                            channelRead(new ChannelHandler(socketChannel, charset), charset.decode(byteBuffer));
                            byteBuffer.clear();
                            socketChannel.read(byteBuffer, timeout, TimeUnit.SECONDS, null, this);

                        }

                        @Override
                        public void failed(Throwable exc, Object attachment) {
                            exc.printStackTrace();
                        }
                    });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void failed(Throwable exc, Object attachment) {
        exc.printStackTrace();
    }

    public abstract void channelActive(ChannelHandler ctx);

    public abstract void channelInactive(ChannelHandler ctx);

    public abstract void channelRead(ChannelHandler ctx, Object msg);
}
